package com.wlyuan.open.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wlyuan.core.exception.ValueError;
import com.wlyuan.mybatis.query.PageUtils;
import com.wlyuan.mybatis.query.QueryUtils;
import com.wlyuan.mybatis.utils.RepositoryUtils;
import com.wlyuan.open.dao.entity.OpenClientDO;
import com.wlyuan.open.dao.mapper.OpenClientMapper;
import com.wlyuan.open.domain.client.OpenClient;
import com.wlyuan.open.domain.client.OpenClientId;
import com.wlyuan.open.domain.client.OpenClientPattern;
import com.wlyuan.open.domain.client.respository.OpenClientRepository;
import com.wlyuan.open.dto.api.OpenClientFilterDTO;
import com.wlyuan.open.infrastructure.config.OpenClientProperties;
import com.wlyuan.open.infrastructure.converter.OpenClientConverter;
import com.wlyuan.utils.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yuanzheng
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OpenClientRepositoryImpl implements OpenClientRepository {
    private final OpenClientMapper openClientMapper;
    private final OpenClientProperties openClientProperties;

    @Override
    public OpenClient ofAppId(@NotNull String appId) {
        QueryWrapper<OpenClientDO> query = new QueryWrapper<>();
        query.lambda().eq(OpenClientDO::getAppId, appId);
        return OpenClientConverter.convert(openClientMapper.selectOne(query));
    }

    @Override
    public OpenClient ofPattern(@NotNull OpenClientPattern pattern) {
        QueryWrapper<OpenClientDO> query = new QueryWrapper<>();
        query.lambda()
                .eq(OpenClientDO::getMobile, pattern.getMobile())
                .or()
                .eq(OpenClientDO::getName, pattern.getName());
        return OpenClientConverter.convert(openClientMapper.selectOne(query));
    }

    @Override
    public OpenClient ofId(@NotNull OpenClientId openClientId) {
        return OpenClientConverter.convert(openClientMapper.selectById(openClientId.getId()));
    }

    @Override
    public OpenClientId save(OpenClient openClient) {
        var applicationDO = RepositoryUtils.save(openClientMapper,
                OpenClientConverter::convert,
                openClient, openClient.getId());

        openClient.setId(new OpenClientId(applicationDO.getId()));
        return openClient.getId();
    }

    @Override
    public void remove(OpenClientId openClientId) {
        throw new ValueError("不允许删除应用");
    }

    @Override
    public Page<OpenClientId> search(OpenClientFilterDTO filter) {
        QueryWrapper<OpenClientDO> query = QueryUtils.build(openClientProperties.getSearch().getRules(), filter);
        query.lambda().orderByDesc(OpenClientDO::getCreateAt);
        var result = openClientMapper.selectPage(PageUtils.page(filter), query);
        return PageUtils.as(result, openClient -> new OpenClientId(openClient.getId()));
    }

    @Override
    public List<OpenClient> list(Collection<OpenClientId> openClientIds) {
        if (CollectionUtils.isEmpty(openClientIds)) {
            return Collections.emptyList();
        }
        List<Long> ids = openClientIds.stream().map(OpenClientId::getId).collect(Collectors.toList());
        LambdaQueryWrapper<OpenClientDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(OpenClientDO::getId, ids).orderByDesc(OpenClientDO::getId);
        return OpenClientConverter.convert(openClientMapper.selectList(queryWrapper));
    }

    @Override
    public OpenClient ofTenantId(Long tenantId, Long userId) {
        QueryWrapper<OpenClientDO> query = new QueryWrapper<>();
        query.lambda().eq(OpenClientDO::getTenantId, tenantId);
        if (userId != null) {
            query.lambda().eq(OpenClientDO::getUserId, userId);
        }
        return OpenClientConverter.convert(openClientMapper.selectOne(query));
    }

    @Override
    public List<OpenClient> ofPatternName(OpenClientPattern pattern) {
        QueryWrapper<OpenClientDO> query = new QueryWrapper<>();
        query.lambda().like(OpenClientDO::getName, pattern.getName());
        return OpenClientConverter.convert(openClientMapper.selectList(query));
    }

    @Override
    public OpenClient ofPatternMobile(OpenClientPattern pattern) {
        QueryWrapper<OpenClientDO> query = new QueryWrapper<>();
        query.lambda().eq(OpenClientDO::getMobile, pattern.getMobile());
        return OpenClientConverter.convert(openClientMapper.selectOne(query));
    }

    @Override
    public List<OpenClient> ofAll() {
        return OpenClientConverter.convert(openClientMapper.selectList(new QueryWrapper<>()));
    }
}
